/*
 * ProductOT.java
 *
 * $Id: ProductOT.java,v 1.8 2009-10-01 10:17:45 mario Exp $
 */
package org.ceteca.explica.core.warehouse;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.ceteca.explica.core.common.BarcodeTypeOT;
import org.ceteca.explica.core.common.BaseVO;
import org.ceteca.explica.core.common.ImageOT;
import org.ceteca.explica.core.common.PriceListOT;
import org.ceteca.explica.core.common.PriceListLineOT;
import org.ceteca.explica.core.common.VatTypeOT;
import org.ceteca.explica.core.traceability.tree.TraceabilityTree;



/**
 * Store class to hold the data of a product.
 * <br/>
 * Responsibilities:
 * <li>
 * 	<ul> Store of product data for exchanging data among presentation, 
 * business and data access layers. </ul>
 * </li>.
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2007 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class ProductOT extends BaseVO implements Serializable {
	/**
	 * Internal id of the product.
	 */
	private long idProduct;
	/**
	 * Description of the product.
	 */
	private String description;
	/**
	 * Reference of the product.
	 */
	private String reference;
	/**
	 * Barcode number of the product.
	 */
	private String barcode;
	/**
	 * Barcode type of the product.
	 */
	private BarcodeTypeOT barcodeType;
	/**
	 * Price of the product.
	 */
	private BigDecimal price;
	/**
	 * Average cost made out of all the suppliers costs.
	 */
	private BigDecimal averageCost;
	/**
	 * Flag to show if sales with no stock are allowed for the product.
	 */
	private boolean allowNoStock;
	/**
	 * Internal id of the product group (Foreign key).
	 */
	private long idGroup;
	/**
	 * Internal id of the product VAT type (Foreign key).
	 */
	private long idVatType;
	/**
	 * Internal id of the product barcode type (Foreign key).
	 */
	private long idBarcodeType;
	/**
	 * Group of the product.
	 */
	private ProductGroupOT group;
	/**
	 * Vat type applied to the product.
	 */
	private VatTypeOT vatType;
	/**
	 * List of product images.
	 */
	private Set images;
	/**
	 * List of product supported measure units.
	 */
	private Set measureUnits;
	/**
	 * List of prices available for the product.
	 */
	private Set prices;
	/**
	 * List of stocks available for the product.
	 */
	private Set stocks;
	
	/**
	 * Traceability information of the product. It's the content bytes
	 * of the traceability tree built for the product.
	 */
	private byte[] trData;
	
	
	/**
	 * Version of the product used by Hibernate for optimistic concurrency control.
	 */
	private Integer version = new Integer(0);
	
	private static final long serialVersionUID = 10000002;
	
	/**
	 * Default ProductOT constructor.
	 */
	public ProductOT() {
	}
	
	/**
	 * Gets the version of the product used by Hibernate for optimistic concurrency control.
	 * @return Integer, version of the group.
	 */
	public Integer getVersion() {
		return version;
	}
	/**
	 * Sets up the version of the product used by Hibernate for optimistic concurrency control.
	 * @param version Integer, version of the group.
	 */
	public void setVersion(Integer version) {
		this.version = version;
	}

	/**
	 * Gets the description of the product.
	 * @return String, description of the product.
	 */
	public String getDescription() {
		return description;
	}
	/**
	 * Sets up the description of the product.
	 * @param description String, description of the product.
	 */
	public void setDescription(String description) {
		this.description = description;
	}

	/**
	 * Gets the identifier of the product.
	 * @return String, identifier of the product.
	 */
	public long getIdProduct() {
		return idProduct;
	}
	/**
	 * Sets up the identifier of the product.
	 * @param idGroup String, identifier of the product.
	 */
	public void setIdProduct(long idProduct) {
		this.idProduct = idProduct;
	}
	
	
	/**
	 * Gets the flag to show that the product can be sold even if there is no stock available in the warehouse. 
	 * @return boolean, True if sales with no stock are admitted; False in any other case.
	 */
	public boolean isAllowNoStock() {
		return allowNoStock;
	}
	/**
	 * Sets up the flag to show that the product can be sold even if there is no stock available in the warehouse. 
	 * @param allowNoStock boolean, True if sales with no stock are admitted; False in any other case.
	 */
	public void setAllowNoStock(boolean allowNoStock) {
		this.allowNoStock = allowNoStock;
	}
	
	/**
	 * Gets the average cost of the product among all the suppliers. 
	 * @return BigDecimal, average cost of the product.
	 */
	public BigDecimal getAverageCost() {
		return averageCost;
	}
	/**
	 * Sets up the average cost of the product among all the suppliers. 
	 * @param averageCost BigDecimal, average cost of the product.
	 */
	public void setAverageCost(BigDecimal averageCost) {
		this.averageCost = averageCost;
	}
	
	/**
	 * Gets the barcode of the product. 
	 * @return String, barcode of the product.
	 */
	public String getBarcode() {
		return barcode;
	}
	/**
	 * Sets up the barcode of the product. 
	 * @param barcode String, barcode of the product.
	 */
	public void setBarcode(String barcode) {
		this.barcode = barcode;
	}

	/**
	 * Gets the barcode's type of the product.
	 * @return BarcodeTypeOT, data of the barcode's type of the product.
	 */
	public BarcodeTypeOT getBarcodeType() {
		return barcodeType;
	}
	/**
	 * Sets up the barcode's type of the product.
	 * @param barcodeType BarcodeTypeOT, data of the barcode's type of the product.
	 */
	public void setBarcodeType(BarcodeTypeOT barcodeType) {
		this.barcodeType = barcodeType;
	}

	/**
	 * Gets the group of the product.
	 * @return ProductGroupOT, data of the group of the product.
	 */
	public ProductGroupOT getGroup() {
		return group;
	}
	/**
	 * Sets up the group of the product.
	 * @param group ProductGroupOT, data of the group of the product.
	 */
	public void setGroup(ProductGroupOT group) {
		this.group = group;
	}

	/**
	 * Gets the price of the product.
	 * @return String, price of the product.
	 */
	public BigDecimal getPrice() {
		return price;
	}
	/**
	 * Sets up the price of the product.
	 * @param price String, price of the product.
	 */
	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	/**
	 * Gets the reference of the product.
	 * @return String, reference of the product.
	 */
	public String getReference() {
		return reference;
	}
	/**
	 * Sets up the reference of the product.
	 * @param reference String, reference of the product.
	 */
	public void setReference(String reference) {
		this.reference = reference;
	}

	/**
	 * Gets the VAT tax that is applied to the product.
	 * @return VatTypeOT, data of the VAT tax type of the product.
	 */
	public VatTypeOT getVatType() {
		return vatType;
	}
	/**
	 * Sets up the VAT tax that is applied to the product.
	 * @param vatType VatTypeOT, data of the VAT tax type of the product.
	 */
	public void setVatType(VatTypeOT vatType) {
		this.vatType = vatType;
	}
	
	/**
	 * Gets the identifier of the product barcode type.
	 * @return long, identifier of the product barcode type (foreign key).
	 */
	public long getIdBarcodeType() {
		return idBarcodeType;
	}
	/**
	 * Sets up the identifier of the product barcode type.
	 * @param idBarcodeType long, identifier of the product barcode type (foreign key).
	 */
	public void setIdBarcodeType(long idBarcodeType) {
		this.idBarcodeType = idBarcodeType;
	}

	/**
	 * Gets the identifier of the product group.
	 * @return long, identifier of the product group (foreign key).
	 */
	public long getIdGroup() {
		return idGroup;
	}
	/**
	 * Sets up the identifier of the product group.
	 * @param idGroup long, identifier of the product group (foreign key).
	 */
	public void setIdGroup(long idGroup) {
		this.idGroup = idGroup;
	}

	/**
	 * Gets the identifier of the product VAT type.
	 * @return long, identifier of the product VAT type (foreign key).
	 */
	public long getIdVatType() {
		return idVatType;
	}
	/**
	 * Sets up the identifier of the product VAT type.
	 * @param idVatType long, identifier of the product VAT type(foreign key).
	 */
	public void setIdVatType(long idVatType) {
		this.idVatType = idVatType;
	}

	/**
	 * Gets the set of product images.
	 * @return Set, product images.
	 */
	public Set getImages() {
		return images;
	}
	/**
	 * Sets up the set of product images.
	 * @param images Set, product images.
	 */
	public void setImages(Set images) {
		this.images = images;
	}
	/**
	 * Adds a new image to the set of product images.
	 * @param image ImageOT, data of the new product image.
	 */
	public void addImage(ImageOT image) {
		this.images.add(image);
	}
	/**
	 * Removes an image from the set of product images.
	 * @param image ImageOT, data of the removed product image.
	 */
	public void delImage(ImageOT image) {
		if (this.images != null && this.images.size() > 0) {
			this.images.remove(image);
		}
	}

	/**
	 * Gets the set of supported product measure units.
	 * @return Set, measure units.
	 */
	public Set getMeasureUnits() {
		return measureUnits;
	}
	/**
	 * Sets up the set of supported product measure units.
	 * @param measureUnits Set, measure units.
	 */
	public void setMeasureUnits(Set measureUnits) {
		this.measureUnits = measureUnits;
	}
	/**
	 * Adds a new measure unit to the set of supported product measure units.
	 * @param measureUnit MeasureUnitOT, data of the new product measure unit.
	 */
	public void addMeasureUnit(MeasureUnitOT measureUnit) {
		this.measureUnits.add(measureUnit);
	}
	/**
	 * Removes a measure unit from the set of supported product measure units.
	 * @param measureUnit MeasureUnitOT, data of the product measure unit.
	 */
	public void delMeasureUnit(MeasureUnitOT measureUnit) {
		if (this.measureUnits != null && this.measureUnits.size() > 0) {
			this.measureUnits.remove(measureUnit);
		}
	}
	
	/**
	 * Gets the set of supported product prices.
	 * @return Set, prices list.
	 */
	public Set getPrices() {
		return prices;
	}
	/**
	 * Sets up the set of supported product prices.
	 * @param prices Set, prices list.
	 */
	public void setPrices(Set prices) {
		this.prices = prices;
	}
	/**
	 * Adds a new price to the set of supported product prices.
	 * @param pll PriceListLineOT, data of the new product price line.
	 */
	public void addPrice(PriceListLineOT pll) {
		this.prices.add(pll);
	}
	/**
	 * Deletes a price from the set of supported product prices.
	 * @param pll PriceListLineOT, data of the product price line.
	 */
	public void delPrice(PriceListLineOT pll) {
		if (this.prices != null && this.prices.size() > 0) {
			this.prices.remove(pll);
		}
	}
	
	/**
	 * Gets the set of available product stocks.
	 * @return Set, stocks list.
	 */
	public Set getStocks() {
		return stocks;
	}
	/**
	 * Sets up the set of available product stocks.
	 * @param stocks Set, stocks list.
	 */
	public void setStocks(Set stocks) {
		this.stocks = stocks;
	}

	/**
	 * Gets the product's traceability data.
	 * @return byte[], product's traceability data.
	 */
	public byte[] getTrData() {
		return this.trData;
	}
	/**
	 * Sets up the product's traceability data.
	 * @param trData byte[], product's traceability data.
	 */
	public void setTrData(byte[] trData) {
		this.trData = trData;
	}

	@Override
    public int hashCode() {
        final HashCodeBuilder hcb = new HashCodeBuilder();
        hcb.append(this.getReference());
        hcb.append(this.getDescription());
        hcb.append(this.getBarcode());

        return hcb.toHashCode();
    }

    
    
    @Override
    public boolean equals(Object obj) {
        boolean isEquals = false;
        try {
            final ProductOT other = (ProductOT)obj;
            final EqualsBuilder eqb = new EqualsBuilder();
            eqb.append(this.getReference(), other.getReference());
            eqb.append(getDescription(), other.getDescription());
            eqb.append(getBarcode(), other.getBarcode());
            isEquals = eqb.isEquals();

        } catch (Exception e) {
            isEquals = false;
        }

        return isEquals;
    }
    
	/**
	 * Implementation of the toString() method to show the data of the ProductOT
	 * formatted.
	 */
	public String toString() {
		StringBuffer result = new StringBuffer();
		try {
			result.append("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
			result.append("\nID: ");
			result.append(this.idProduct);
			result.append("\nREFERENCE: ");
			result.append(this.reference);
			result.append("\nBARCODE: ");
			result.append(this.barcode);
			result.append("\nBARCODE TYPE: ");
			result.append(this.barcodeType);
			result.append("\nDESCRIPTION: ");
			result.append(this.description);
			result.append("\nPRICE: ");
			result.append(this.price);
			result.append("\nVAT TYPE: ");
			result.append(this.vatType);
			result.append("\nAVERAGE COST: ");
			result.append(this.averageCost);
			result.append("\nIMAGES: ");
			result.append(this.images.size());
			result.append("\nGROUP: ");
			result.append(this.group);
			result.append("\nALLOW NO STOCK: ");
			result.append(this.allowNoStock);
			result.append("\n\nTRACEABILITY DATA: ");
			result.append(this.trData);
			
			result.append("\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
		}
		catch (Exception ex) {
			System.out.println("Error formatting ProductOT!");
			ex.printStackTrace();
			return null;
		}
		
		return result.toString();
	}
	
	@Override
	public boolean equals(Long id) {
		return id != null && this.idProduct == id.longValue();
	}
	
	@Override
	public long getInternalId() {
		return this.idProduct;
	}

	@Override
	public String getInternalValue() {
		return this.description;
	}
	
	@Override
	public String getEntityId() {
		return InterfaceWarehouse.EXPLICA_ENTITY_PRODUCT_ID;
	}

	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: ProductOT.java,v 1.8 2009-10-01 10:17:45 mario Exp $";
	}	
}
